<?php

/**
 * @copyright ©2022 QuickAdmin
 * @author QinTingWei
 * @link http://www.quickadmin.cn/
 * Date Time: 2023/10/26
 */

namespace quick\admin\http\model;


use quick\admin\library\tools\CsvExport;
use think\Exception;

abstract class CommonImport
{

    public $fieldsKeyList;


    public $fieldsNameList;


    public $dirName = 'test';

    /**
     * 数据源
     * @var
     */
    public $dataList;


    private $exportFields = [];

    private $exportIds = [];

    private $key = 'id';

    /**
     * @var
     */
    public $query;

    abstract public function fieldsList();


    /**
     * @param $query
     * @return mixed
     */
    abstract public function export($query);

    /**
     * 数据转换
     * @param $list
     * @return mixed
     */
    abstract protected function transform(array $list);

    /**
     * 处理导入数据，数据持久化
     * @param array $data
     * @return bool
     */
    abstract public function handleDataStore(array $data): bool;


    public function getTemplateName()
    {
        return "模板";
    }


    protected function validate(array $list): bool
    {
        return true;
    }


    public function import(string $filePath)
    {
        if (!file_exists($filePath)) {
            throw new Exception(__("文件不存在"));
        }
        if (pathinfo($filePath, PATHINFO_EXTENSION) === 'csv') {
            $data = $this->getCSV($filePath);
        } else {
            $data = $this->getExcel($filePath);
        }

        $headerArr = array_shift($data);
        $headerFieldsArr = [];
        foreach ($headerArr as $item) {
            foreach ($this->getHeaderFields() as $key => $name) {
                if ($name === $item) {
                    $headerFieldsArr[] = $key;
                }
            }
        }

        if (count($this->getHeaderFields()) != count($headerFieldsArr)) {
            throw new \Exception(__("导入文件头部字段不正确"));
        }

        $dataList = [];
        foreach ($data as $key => $row) {
            $newRow = [];
            $rowNum = $key + 1;
            foreach ($row as $j => $value) {
                if (isset($headerFieldsArr[$j])) {
                    $newRow[$headerFieldsArr[$j]] = $value;
                }
            }

            if (count($newRow) != count($headerFieldsArr)) {
                throw new \Exception(__("数据内容不完整,第{$rowNum} 行"));
            }

            try {
                if (!$this->validate($newRow)) {
                    throw new \Exception('数据格式有误');
                }
            } catch (\Exception $e) {
                throw new \Exception(__("数据内容不完整,第{$rowNum} 行;" . $e->getMessage()));
            }

            $newRow = $this->transform($newRow);

            $dataList[] = $newRow;
        }

        $this->handleDataStore($dataList);

        return $dataList;
    }


    /**
     * 获取导入头部字段
     * @return array
     */
    public function getHeaderFields()
    {
        $fields = $this->fieldsList();
        $data = [];
        foreach ($fields as $item) {
            $data[$item['key']] = $item['name'];
        }
        return $data;
    }


    /**
     * 下载模板
     * @param string $name
     */
    public function template($name = '模板')
    {

        $data = [];
        $headerArr = $this->getHeaderFields();
        $csvService = new CsvExport();
        $csvService->export($data, $headerArr, $name);
    }


    public function getExcel($file)
    {
        $PHPExcel = \PHPExcel_IOFactory::load($file);
        $sheet = $PHPExcel->getSheet(0); // 读取第一個工作表
        $highestRow = $sheet->getHighestRow(); // 取得总行数
        $highestColumm = $sheet->getHighestColumn(); // 取得总列数

        // 把Excel数据保存数组中
        $data = array();
        for ($rowIndex = 1; $rowIndex <= $highestRow; $rowIndex++) {
            for ($colIndex = 'A'; $colIndex <= $highestColumm; $colIndex++) {
                $addr = $colIndex . $rowIndex;
                $cell = $sheet->getCell($addr)->getFormattedValue();
                if ($cell instanceof PHPExcel_RichText) {
                    $cell = $cell->__toString();
                }
                $data[$rowIndex][] = trim($cell);
            }
        }
        return $data;
    }


    protected function getCSV($file)
    {
        $arrCSV = array();
        if (($handle = fopen($file, "r")) !== false) {
            $key = 0;
            while (($data = fgetcsv($handle, 0, ",")) !== false) {
                $c = count($data);
                for ($x = 0; $x < $c; $x++) {
                    $arrCSV[$key][$x] = $this->check(trim($data[$x]));
                }
                $key++;
            }
            fclose($handle);
        }

        return $arrCSV;
    }


    //判断是否含有英文逗号，英文引号
    public function check($value)
    {
        if (!$this->checkJson($value)) {
            $isInt = is_int($value) ? true : false;
            $isFloat = is_float($value) ? true : false;

            $value = rtrim($value, "\r\n");
            $value = str_replace(",", "，", $value);

            $value = is_string($value) ? $value . "\t" : $value;
            $value = $isInt ? intval($value) : $value;
            $value = $isFloat ? floatval($value) : $value;
        }
        $encode = mb_detect_encoding($value, array("ASCII", 'UTF-8', "GB2312", "GBK", 'BIG5'));
        $value = mb_convert_encoding($value, 'UTF-8', $encode);

        return str_replace("\t", "", $value);
    }

    // 判断是否为json数据
    private function checkJson($value)
    {
        if (empty($value)) {
            return false;
        }
        $data = json_decode($value);
        if ($data && (is_object($data)) || is_array($data)) {
            return true;
        }

        return false;
    }
}